# -*- coding: utf-8 -*-
# © 2018 QYT Technology
# Authored by: Zhao Xingtao (zxt50330@gmail.com)
from flask import request, jsonify
from flask.views import MethodView

from bills.services.model import db


class APIView(MethodView):
    """
    VIEW 基类 TODO: 待完成
    """
    model = None
    name = ''
    path = '/'
    allowed_actions = (
        'create',
        'list',
        'retrieve',
        'update',
        'upsert',
        'destroy',
    )
    pk_field = 'id'
    schema_mapping = {}
    serializer_class = None
    serializer_detail_class = serializer_class

    def __init__(self):
        self._context = {}
        self._serializer_instances = {}
        super(APIView, self).__init__()

    @property
    def _create_schema(self):
        return self.schema_mapping.get('create', self.schema_mapping.get('default', None))

    def new_obj(self, extra_payload=None, *args, **kwargs):
        """ 新建项目逻辑, 子类可覆盖

            Nested API需要自定义此方法

        """
        if self._create_schema:
            # payload = self._payload_processor(request.get_json(silent=True))
            payload = request.get_json(silent=False)
            # if not payload:
            #     payload = {}
            # payload['cid'] = self.cid
            # print 'payload=======%s' % payload, self._create_schema
            load_result = self._create_schema.load(payload)
            # if load_result.errors:
            #     raise exceptions.SchemaValidationError(errors=load_result.errors)
            #
            obj = load_result.data
            #
            # if hasattr(obj, 'cid'):
            #     obj.cid = self.cid
        #
        else:
            payload = self._payload_processor(request.get_json(silent=True))
            if not payload:
                payload = {}
            if not extra_payload:
                extra_payload = {}
        #
            obj = self.get_model()(**extra_payload)
        #     if hasattr(self.get_model(), 'cid'):
        #         obj.cid = self.cid
        #     if hasattr(self.get_model(), 'uid'):
        #         obj.uid = self.uid
        #
        #     obj = self._set_obj_property(obj, payload,
        #                                  quiet=kwargs.get('quiet', False))
        #     obj.id = kwargs.get('id')
        #
        #     # legacy model手动维护ctime
        #     if self.legacy_model and hasattr(obj, 'ctime'):
        #         ctime = time.time()
        #         obj.ctime = ctime
        #         if hasattr(obj, 'utime'):
        #             obj.utime = ctime

        return obj


    def create(self, *args, **kwargs):
        """ 新增接口 (CREATE) """
        # for perm in self.permission_model_level_mapping['create']:
        #     self.check_model_permission(perm)
        obj = self.new_obj(*args, **kwargs)

        db.session.add(obj)
        db.session.commit()

    def post(self, *args, **kwargs):
        return self.create(*args, **kwargs)

    def get(self, pk=None, *args, **kwargs):
        """ dispatch GET 方法到LIST与RETRIEVE endpoint
        """
        if pk is not None:
            return self.retrieve(pk, *args, **kwargs)
        else:
            return self.list(*args, **kwargs)

    def get_object(self, pk=None, raise_404=True, *args, **kwargs):
        query = self.get_query(*args, **kwargs)
        field = getattr(self.get_model(), self.pk_field)
        if raise_404:
            obj = query.filter(field == pk).first_or_404()
        else:
            obj = query.filter(field == pk).first()
        return obj

    def serialize(self, obj):
        return self.serializer_detail_class().dump(obj).data

    def retrieve(self, pk, *args, **kwargs):
        """ 详情接口 (RETRIEVE) """
        obj = self.get_object(pk, *args, **kwargs)
        return self.serialize(obj)

    def list(self, *args, **kwargs):
        """ 列表接口 (LIST) """
        query = self.get_query(*args, **kwargs)
        result_list = self.serialize_many(query)

        return result_list

    def serialize_many(self, queryset, serializer_class=None):
        return self._to_dict(queryset, many=True, serializer_class=serializer_class)

    # def _to_dict(self, instance, many=False, serializer_class=None):
    #     self._serializer_instances[serializer_class] = serializer_class(many=many, context=context)
    #     result = self._serializer_instances[serializer_class].dump(instance)
    #     return result.data

    def get_query(self, session=None):
        """ 默认获取查询方法, 子类可覆盖本方法实现自定义过滤

            Nested API需要自定义此方法

        """
        if session:
            query = self.get_model().query_class(self.get_model(), session=session)
            print('---using custom session---')
        else:
            query = self.get_model().query
        return query

    def get_model(self):
        return self.model

    def dispatch_request(self, *args, **kwargs):
        result = super(APIView, self).dispatch_request(*args, **kwargs)
        return jsonify(result)